package com.lightman.gulimall.search.thread;


import java.util.concurrent.*;

public class ThreadTest {

    public static ExecutorService service = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {

        System.out.println("main 方法开始了");
        /**
         * 1、继承Thread  new Thread01().start();
         * 2、实现Runnable接口
         *              Runable01 runable01 = new Runable01();
         *         new Thread(runable01).start();
         * 3、实现callable 接口,+ futureTask (可以拿到返回结果, 乐意处理异常)
         *        FutureTask<Integer> futureTask = new FutureTask<>(new callable01());
         *         new Thread(futureTask).start();
         *
         *         // 阻塞等待整个线程执行完成,获得返回结果
         *         Integer integer = futureTask.get();
         * 4、线程池
         *      给线程池提交线程
         *
         *      1、 创建
         *          1 ) Executors
         *          2 ) new ThreadPoolExecutor(7大参数)
         *
         * 区别:
         *  1 、 2 不能得到返回值, 3 可以获取返回值
         *  1 、2 、 3 都不能控制资源
         *  4 可以控制资源, 性能稳定
         */

//        new Thread01().start();
//        Runable01 runable01 = new Runable01();
//        new Thread(runable01).start();

        // 我们以后在业务代码里面,以上三种启动线程发的方式都不使用， 【将所有的多线程异步任务都交给线程执行】
//        new Thread(()->{
//            System.out.println("hello");
//        }).start();

        // 当前系统中只有一两个, 每个异步任务都提交给线程池让他自己去执行


//        service.execute(new Runable01());


        /**
         * 七大参数
         *
         * int corePoolSize, 核心线程数[一直存在,除非设置允许核心线程数超时(allowCareThreadTimeOut)]: 线程池,创建好以后就准备就绪的线程数量, 就等待接收异步任务去执行
         *                              相当于  new Thread() N 个,没有调用start()方法
         *
         * int maximumPoolSize, 最大线程数 控制资源
         *
         * long keepAliveTime, 存活时间 , 如果当前线程数量大于核心线程数量, 释放空闲线程, 只要线程空闲大于指定的时间
         *                                  释放的是非核心线程,核心线程是不释放的
         *
         * TimeUnit unit,  时间单位
         *
         * BlockingQueue<Runnable> workQueue, 阻塞队列,如果任务有很多,就会将目前最多的任务放在队列里面
         *                                      只要有了空线程,就回去队列里面获取线程,继续执行
         *
         * ThreadFactory threadFactory, 线程创建工厂
         *
         * RejectedExecutionHandler handler : 如果队列满了,按照我们指定的拒绝策略 执行任务
         *
         *  工作顺序:
         *      1)、线程池创建,准备好core数量的核心线程,准备接受任务
         *      1.1 core线程满了,就会将进来的任务放在阻塞队列里面,空闲的core就会自己去阻塞队列获取任务执行.
         *      1.2、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         *      1.3、max 满了就用 RejectedExecutionHandler 拒绝任务
         *      1.4、max 都执行 完成,有很多空闲,在指定keepAliveTime 以后,释放 max-core 这些线程
         *
         *          new LinkedBlockingDeque<>() , 默认是Integer的最大值. 内存不够
         *
         *          —个线程池core 7;max 20 , queue: 5e，1ee并发进来怎么分配的;
         *          7个会立即得到执行，50个会进入队列，再开13个进行执行。剩下的30个就使用拒绝策略。如果不想抛弃还要执行。callerRunsPolicy:
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000), Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

//        Executors.newCachedThreadPool(); core是0, 所有的都可以回收
//        Executors.newFixedThreadPool(); core = max 都不可回收
//        Executors.newScheduledThreadPool(); 定时任务线池
//        Executors.newSingleThreadExecutor(); 单线程池 core = max= 1; 后台从队列里面湖区任务,挨个执行

        System.out.println("-----------main ---------");
    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果 " + i);
        }
    }

    public static class Runable01 implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果 " + i);
        }
    }


    public static class callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果 " + i);
            return i;
        }
    }
}
